﻿/*
BF3 RCON Simulator simulates the RCON interface of a BF3 server.
Copyright (C) 2011 Timi

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.

You can contact us at http://bf3sim.codeplex.com/.
*/

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Globalization;

namespace BF3RconSimulator
{
    //provides a simple class for determining if a number is within a range.
    //will be used in varsdata to see if the set for certain values is in a certain range
    //always inclusive
    abstract class NumericRange
    {
        internal abstract bool IsInRange<TValue>(TValue value) where TValue : IComparable<TValue>;
        internal abstract bool IsInRange(string value);// where TValue : IComparable<TValue>, IConvertible;
        internal abstract ValueType DefaultValue();
    }

    //will be used by other classes because numberstyles will be used for integer types
    abstract class NumericRange<T> : NumericRange where T:struct, IComparable<T>, IConvertible
    {
        internal T Min { get; private set; }
        internal T Max { get; private set; }

        bool IsInRange(IComparable<T> value)
        {
            //< min
            if (value.CompareTo(Min) < 0) return false;

            //> max
            if (value.CompareTo(Max) > 0) return false;

            return true; //now must be in range
        }

        internal override bool IsInRange<TValue>(TValue value)
        {
            return IsInRange(value);
        }

        internal abstract override bool IsInRange(string value);

        internal NumericRange(T min, T max)
        {
            Min = min;
            Max = max;
        }

        internal override ValueType DefaultValue()
        {
            return default(T); //TODO: consider making customizable in the case of inconsistent output
        }
    }

    class UIntegerRange : NumericRange<uint>
    {
        internal override bool IsInRange(string value)
        {
            
            try
            {
                uint realValue = uint.Parse(value, NumberStyles.Integer | NumberStyles.Float, NumberFormatInfo.InvariantInfo);
                return IsInRange(realValue);
            }
            catch (OverflowException)
            {
                //TODO: see what happens if a negative is sent in vars.*. will need to handle overflow exception tho
                return false;
            }
            catch (FormatException)
            {
                //TODO: check for an error packet saying invalid format.
                //if different output, make nullable
                return false;
            }
            
            //TODO: check to see if vars.* allow whitespace
            //if more than 3 outputs for false, return something other than bool? or bool
        }

        internal UIntegerRange(uint min, uint max) : base(min, max)
        {

        }
    }
}
